home *** CD-ROM | disk | FTP | other *** search
- /**
- * Copyright (c) 2008, Jose Enrique Bolanos, Jorge Villalobos
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of Jose Enrique Bolanos, Jorge Villalobos nor the names
- * of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- **/
-
- var EXPORTED_SYMBOLS = [];
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Ce = Components.Exception;
-
- Components.utils.import("resource://firefm/fmCommon.js");
- Components.utils.import("resource://firefm/fmPlayer.js");
-
- // Name of the permission file
- const PERMISSION_FILE_NAME = "firefm.cfg";
- // Strings passed to the directory service to obtain the application data
- // folder on each OS
- const LOCATIONS = [
- // Windows
- "AppData",
- // Mac
- "UsrPrfs",
- // Unix
- "Home"
- ];
- // Directory path to the permission file for each OS
- const DIR_PATH = [
- // Windows
- ["Macromedia", "Flash Player", "#Security", "FlashPlayerTrust"],
- // Mac
- ["Macromedia", "Flash Player", "#Security", "FlashPlayerTrust"],
- // Unix
- [".macromedia", "Flash_Player", "#Security", "FlashPlayerTrust"]
- ];
-
- // UUIDs of extensions that interfere with Fire.fm
- const NOSCRIPT_UUID = "{73a6fe31-595d-460b-a920-fcc0f8843232}";
- const FLASHBLOCK_UUID = "{3d7eb24f-2740-49df-8937-200b1cc08f8a}";
- const STOPAUTOPLAY_UUID = "{2e61e246-e640-4c56-b1ed-f146dbed48cd}";
- const MEDIAWRAP_UUID = "{dd68c513-9296-4b63-8d8b-8f1c991c8a48}";
-
- // Flashblock and similar extensions timeout.
- const FLASHBLOCK_TIMEOUT = 100;
-
- /**
- * FireFM Player Initializer. Performs all the flash player intialization tasks.
- */
- FireFM.PlayerInitializer = {
-
- /* Logger for this object */
- _logger : null,
- /* Holds the exception that may have been thrown during initialization */
- _initializationException : null,
-
- /**
- * Initializes the object.
- */
- init : function() {
- this._logger = FireFM.getLogger("FireFM.PlayerInitializer");
- this._logger.debug("init");
-
- this._initializeFlashPlayer();
- },
-
- /**
- * Obtains the exception that may have been thrown during the flash player
- * initialization. Null if no exception was thrown.
- */
- get initializationException() {
- this._logger.debug("initializationException[get]");
- return this._initializationException;
- },
-
- /**
- * Initializes the flash object needed to play mp3 files. Steps:
- * 1. The flash plugin is detected.
- * 2. The flash player URL is calculated.
- * 3. The flash player permission file is installed.
- * 4. The flash player object is injected in the hidden window.
- * After the initialization tasks are complete, FireFM.Player is initialized
- * with the results.
- */
- _initializeFlashPlayer : function() {
- this._logger.trace("_initializeFlashPlayer");
-
- try {
- // test error line. Comment out on releases!
- //null.hello;
-
- if (this._detectFlashPlugin()) {
- let flashURL = this._getFlashURL();
-
- this._installPermissionFile(flashURL);
-
- if (this._isExtensionInstalled(NOSCRIPT_UUID)) {
- this._overrideNoscript(flashURL);
- }
-
- // these add-ons use bindings with CSS in order to change embed
- // elements. We use our own CSS to override them.
- if (this._isExtensionInstalled(FLASHBLOCK_UUID) ||
- this._isExtensionInstalled(STOPAUTOPLAY_UUID) ||
- this._isExtensionInstalled(MEDIAWRAP_UUID)) {
- let that = this;
- let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- // XXX: we need a timeout here because we need to give the add-ons
- // enough time to finish setting up. This way we're sure that our
- // measures will work correctly.
- timer.initWithCallback(
- { notify :
- function(aTimer) {
- that._overrideFlashCSS();
- that._finishPlayerInit(flashURL);
- }
- },
- FLASHBLOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
- } else {
- this._finishPlayerInit(flashURL);
- }
- } else {
- this._logger.warn("Flash plugin missing");
- FireFM.Player.initializePlayer(
- null, FireFM.Player.STATUS_PLUGIN_MISSING);
- }
- } catch (e) {
- this._logger.fatal("Flash player initialization failed:\n" + e);
- this._initializationException = e;
- FireFM.Player.initializePlayer(null, FireFM.Player.STATUS_LOAD_ERROR);
- }
- },
-
- /**
- * Finishes the initialization of the Flash player.
- * @param aURL the url of the Flash file to load.
- */
- _finishPlayerInit : function(aURL) {
- this._logger.trace("_finishPlayerInit");
-
- let flashObject = this._injectFlash(aURL);
-
- this._logger.info("Flash player initialized successfully");
- FireFM.Player.initializePlayer(flashObject, FireFM.Player.STATUS_READY);
- },
-
- /**
- * Detects if the flash player plugin is installed, enabled, and of the
- * required version.
- * @return True of the plugin meets the requirements, false otherwise.
- */
- _detectFlashPlugin : function() {
- this._logger.trace("_detectFlashPlugin");
-
- // Regular expression to obtain the flash plugin version from its
- // description.
- const REGEX_FLASH_VERSION = /([0-9]+)[^0-9]/gi;
- // Minimum flash version supported
- const MIN_FLASH_VERSION = 8;
-
- let isValidPlugin = false;
-
- let plugin =
- Cc["@mozilla.org/appshell/appShellService;1"].
- getService(Ci.nsIAppShellService).hiddenDOMWindow.
- navigator.mimeTypes["application/x-shockwave-flash"];
-
- if (plugin && plugin.enabledPlugin && plugin.enabledPlugin.description) {
-
- let match = REGEX_FLASH_VERSION.exec(plugin.enabledPlugin.description);
- if (match && match.length > 0) {
- isValidPlugin = (MIN_FLASH_VERSION <= parseInt(match[1]));
- }
- }
-
- return isValidPlugin;
- },
-
- /**
- * Obtains the URL of the flash player, located in the extension's default
- * folder.
- * @return The URL of the flash player.
- */
- _getFlashURL : function() {
- this._logger.trace("_getFlashURL");
-
- // Flash file name
- const FLASH_FILE_NAME = "firefm.swf";
- let flashFile;
- let flashURL;
-
- try {
- let extensionManager =
- Cc["@mozilla.org/extensions/manager;1"].
- getService(Ci.nsIExtensionManager);
-
- flashFile =
- extensionManager.
- getInstallLocation(FireFM.EXTENSION_UUID).
- getItemLocation(FireFM.EXTENSION_UUID);
- flashFile.append("defaults");
- flashFile.append(FLASH_FILE_NAME);
-
- } catch (e) {
- let directoryService =
- Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties);
-
- flashFile = directoryService.get("ProfD", Ci.nsIFile);
- flashFile.append("extensions");
- flashFile.append(FireFM.EXTENSION_UUID);
- flashFile.append("defaults");
- flashFile.append(FLASH_FILE_NAME);
- }
-
- flashURL =
- Cc["@mozilla.org/network/protocol;1?name=file"].
- getService(Ci.nsIFileProtocolHandler).getURLSpecFromFile(flashFile);
-
- return flashURL;
- },
-
- /**
- * Installs the permission file required for the embedded flash object to
- * connect to the Internet. If the permission file and entry already exist
- * then the file is not altered.
- * @param aFlashURL The URL of the flash player, used in the permission file.
- */
- _installPermissionFile : function(aFlashURL) {
- this._logger.trace("_installPermissionFile");
-
- let permissionFile = this._getPermissionFile();
- let data =
- "resource://gre/res/hiddenWindow.html\n" +
- "chrome://browser/content/hiddenWindow.xul\n" +
- "chrome://firefm/content/fmVideoDialog.xul\n" +
- decodeURIComponent(aFlashURL);
-
- let foStream =
- Cc["@mozilla.org/network/file-output-stream;1"].
- createInstance(Ci.nsIFileOutputStream);
- let coStream =
- Cc["@mozilla.org/intl/converter-output-stream;1"].
- createInstance(Ci.nsIConverterOutputStream);
-
- // write, create, truncate
- foStream.init(permissionFile, 0x02 | 0x08 | 0x20, 0666, 0);
- coStream.init(foStream, "UTF-8", 0, 0);
- coStream.writeString(data);
- coStream.close();
- foStream.close();
-
- this._logger.debug("Flash permission file written");
- },
-
- /**
- * Obtains a reference to the flash permission file.
- * @return The file permission file reference.
- */
- _getPermissionFile : function() {
- this._logger.trace("_getPermissionFile");
-
- let osIndex = 2;
-
- switch (FireFM.getOperatingSystem()) {
- case FireFM.OS_WINDOWS:
- case FireFM.OS_WINDOWS_VISTA:
- osIndex = 0;
- break;
- case FireFM.OS_MAC:
- osIndex = 1;
- break;
- }
-
- let file =
- Cc["@mozilla.org/file/directory_service;1"].
- getService(Ci.nsIProperties).
- get(LOCATIONS[osIndex], Ci.nsIFile);
-
- // Move towards target path
- for (let i = 0; i < DIR_PATH[osIndex].length; i++) {
- file.append(DIR_PATH[osIndex][i]);
-
- if (!file.exists() || !file.isDirectory()) {
- file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
- }
- }
-
- file.append(PERMISSION_FILE_NAME);
-
- return file;
- },
-
- /**
- * Injects the embedded flash player object needed to play mp3 files in the
- * hidden window.
- * @param aFlashURL The URL from where to load the flash player.
- */
- _injectFlash : function(aFlashURL) {
- this._logger.trace("_injectFlash");
-
- let win =
- Cc["@mozilla.org/appshell/appShellService;1"].
- getService(Ci.nsIAppShellService).hiddenDOMWindow;
- let doc = win.document;
-
- let playerObj =
- doc.createElementNS("http://www.w3.org/1999/xhtml", "embed");
-
- playerObj.setAttribute("src", aFlashURL);
- playerObj.setAttribute("type", "application/x-shockwave-flash");
- playerObj.setAttribute("id", "firefm-player");
- playerObj.setAttribute("name", "firefm-player");
- playerObj.setAttribute("FlashVars", "id='firefm-player'");
- playerObj.setAttribute("allowScriptAccess", "always");
- playerObj.setAttribute("quality", "high");
-
- doc.documentElement.appendChild(playerObj);
-
- win.onFireFMSoundLoad = function(aId, aSuccess) {
- FireFM.Player.onTrackLoaded(aSuccess);
- };
-
- win.onFireFMSoundComplete = function(aId) {
- FireFM.Player.onTrackFinished();
- };
-
- win.addEventListener(
- "unload",
- function() {
- win.onFireFMSoundLoad = null;
- win.onFireFMSoundComplete = null;
- FireFM.Player.uninitializePlayer();
- },
- false);
-
- return playerObj;
- },
-
- /**
- * Determines whether the extension identified by aExtensionId is intalled.
- * @return True if installed, false otherwise.
- */
- _isExtensionInstalled : function(aExtensionId) {
- this._logger.trace("_isExtensionInstalled");
- return (null != FireFM.Application.extensions.get(aExtensionId));
- },
-
- /**
- * Unblocks the Fire.fm player when it is blocked by certain extensions. A
- * style sheet that removes a special -moz-binding rule for flash embeds is
- * registered. This task has to be performed after every browser window loads.
- */
- _overrideFlashCSS : function() {
- this._logger.trace("_overrideFlashCSS");
-
- let sss =
- Cc["@mozilla.org/content/style-sheet-service;1"].
- getService(Ci.nsIStyleSheetService);
- let overrideSheetURL =
- FireFM.createURI("chrome://firefm/content/overrideFlashblock.css");
-
- sss.loadAndRegisterSheet(overrideSheetURL, sss.USER_SHEET);
- this._logger.info("CSS Flash blocking overridden");
- },
-
- /**
- * Sets the Fire.fm flash player as an allowed object using the NoScript
- * service.
- * @param aFlashURL The URL of the flash player.
- */
- _overrideNoscript : function(aFlashURL) {
- this._logger.trace("overrideNoscript");
-
- try {
- // the extension could be disabled.
- if ("@maone.net/noscript-service;1" in Cc) {
- let noscriptService =
- Cc["@maone.net/noscript-service;1"].getService().wrappedJSObject;
- noscriptService.setAllowedObject(
- aFlashURL, "application/x-shockwave-flash");
- }
- } catch (e) {
- this._logger.warn("Error overriding Noscript: " + e);
- }
- }
- };
-